package com.zh.parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import com.zh.util.StringUtil;

/**
 * https://www.bilibili.com/video/BV1zW411t7YE?p=20
 * 语法转换
 */
public class ParserTransform {

    /** 非终结符 */
    private Set<Integer> noStopChar;

    /** 终结符 **/
    private Set<Integer> stopChar = new HashSet<>();

    private Set<Integer> allChar = new HashSet<>(64);
    
    /** 符号 转 int **/
    private Map<String, Integer> char2int = new HashMap<>(64);
    /** int 转 符号 **/
    private Map<String, Integer> int2char = new HashMap<>(64);
    
    private Map<Integer, Set<R>> roleMap = new HashMap<>();
    
    public void addRole(String role, String... values) {
    	int i = getCharInt(role);
    	noStopChar.add(i);
    	allChar.add(i);
    	R r = new R();
    	for (String str : values) {
    		String[] ss = str.split(" ");
    		for (String s : ss) {
	    		if (StringUtil.isEmply(s))
	    			continue;
	    		int ii = getCharInt(s);
	    		allChar.add(ii);
	    		r.addR(ii);
    		}
    	}
    	addRole(i, r);
    }
    
    private void addRole(int role, R r) {
    	if (!roleMap.containsKey(role))
    		roleMap.put(role, new HashSet<>());
    	roleMap.get(role).add(r);
    }
    
    
    public void handle() {
    	Set<Integer> ts = new HashSet<>(allChar);
    	ts.removeAll(stopChar);
    	noStopChar = ts;
    	
    }
    
    /**
     * 处理直接左递归
     */
    private void handleA() {
    	
    }
    
    
    public int getCharInt(String s) {
    	if (!char2int.containsKey(s)) {
			char2int.put(s, char2int.size());
		}
		return char2int.get(s);
    }
    
    class R {
    	List<Integer> li = new ArrayList<>();
    	R(String... strs) {
    		for (String s : strs) {
    			addR(s);
    		}
    	}
    	R() {}
    	
    	void addR(String s) {
			li.add(getCharInt(s));
    	}
    	
    	void addR(Integer i) {
    		li.add(i);
    	}
    	
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result;
			result = prime * result + Objects.hash(li);
			return result;
		}
		
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			R other = (R) obj;
			return Objects.equals(li, other.li);
		}
    	
    }
}
